package com.example.flower_shop.service.impl;

import com.example.flower_shop.dto.address.AddressDTO;
import com.example.flower_shop.entity.Address;
import com.example.flower_shop.entity.User;
import com.example.flower_shop.exception.BusinessException;
import com.example.flower_shop.exception.ResourceNotFoundException;
import com.example.flower_shop.repository.AddressRepository;
import com.example.flower_shop.repository.UserRepository;
import com.example.flower_shop.service.AddressService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class AddressServiceImpl implements AddressService {

    private final AddressRepository addressRepository;
    private final UserRepository userRepository;

    @Override
    public List<AddressDTO> getAddressList(Long userId) {
        List<Address> addresses = addressRepository.findByUserId(userId);
        return addresses.stream()
                .map(AddressDTO::new)
                .collect(Collectors.toList());
    }

    @Override
    public AddressDTO getAddress(Long userId, Long addressId) {
        Address address = addressRepository.findByIdAndUserId(addressId, userId)
                .orElseThrow(() -> new ResourceNotFoundException("收货地址", addressId));
        return new AddressDTO(address);
    }

    @Override
    @Transactional
    public AddressDTO createAddress(Long userId, AddressDTO addressDTO) {
        User user = userRepository.findById(userId)
                .orElseThrow(() -> new ResourceNotFoundException("用户", userId));

        Address address = new Address();
        address.setUser(user);
        address.setReceiverName(addressDTO.getReceiverName());
        address.setReceiverPhone(addressDTO.getReceiverPhone());
        address.setProvince(addressDTO.getProvince());
        address.setCity(addressDTO.getCity());
        address.setDistrict(addressDTO.getDistrict());
        address.setDetailAddress(addressDTO.getDetailAddress());
        address.setIsDefault(addressDTO.getIsDefault());

        if (Boolean.TRUE.equals(address.getIsDefault())) {
            addressRepository.clearOtherDefaultAddress(userId, null);
        }

        address = addressRepository.save(address);
        return new AddressDTO(address);
    }

    @Override
    @Transactional
    public AddressDTO updateAddress(Long userId, Long addressId, AddressDTO addressDTO) {
        Address address = addressRepository.findByIdAndUserId(addressId, userId)
                .orElseThrow(() -> new ResourceNotFoundException("收货地址", addressId));

        address.setReceiverName(addressDTO.getReceiverName());
        address.setReceiverPhone(addressDTO.getReceiverPhone());
        address.setProvince(addressDTO.getProvince());
        address.setCity(addressDTO.getCity());
        address.setDistrict(addressDTO.getDistrict());
        address.setDetailAddress(addressDTO.getDetailAddress());
        address.setIsDefault(addressDTO.getIsDefault());

        if (Boolean.TRUE.equals(address.getIsDefault())) {
            addressRepository.clearOtherDefaultAddress(userId, addressId);
        }

        address = addressRepository.save(address);
        return new AddressDTO(address);
    }

    @Override
    @Transactional
    public void deleteAddress(Long userId, Long addressId) {
        Address address = addressRepository.findByIdAndUserId(addressId, userId)
                .orElseThrow(() -> new ResourceNotFoundException("收货地址", addressId));
        addressRepository.delete(address);
    }

    @Override
    @Transactional
    public AddressDTO setDefaultAddress(Long userId, Long addressId) {
        Address address = addressRepository.findByIdAndUserId(addressId, userId)
                .orElseThrow(() -> new ResourceNotFoundException("收货地址", addressId));

        addressRepository.clearOtherDefaultAddress(userId, addressId);
        address.setIsDefault(true);
        address = addressRepository.save(address);
        return new AddressDTO(address);
    }

    @Override
    public AddressDTO getDefaultAddress(Long userId) {
        return addressRepository.findByUserIdAndIsDefaultTrue(userId)
                .map(AddressDTO::new)
                .orElseThrow(() -> new BusinessException("NO_DEFAULT_ADDRESS", "未设置默认收货地址"));
    }
}